' This class permits you to perform direct connections to FTP sites in Visual Basic. NET.
' The class supports the following FTP commands:
'   - Upload a file
'   - Download a file
'   - Create a directory
'   - Remove a directory
'   - Change directory
'   - Remove a file
'   - Rename a file
'   - Set the user name of the remote user
'   - Set the password of the remote user

Imports System
Imports System.Net
Imports System.IO
Imports System.Text
Imports System.Net.Sockets

Namespace Network
    'FTP Class
    Public Class FTP
#Region "Class Variable Declarations"
        Private m_sRemoteHost, m_sRemotePath, m_sRemoteUser As String
        Private m_sRemotePassword, m_sMess As String
        Private m_iRemotePort, m_iBytes As Int32
        Private m_objClientSocket As Socket
        Private m_sReceiveTimeout As Integer
        Private m_sSendTimeout As Integer
        Private m_iRetValue As Int32
        Private m_bLoggedIn As Boolean
        Private m_sMes, m_sReply As String

        'Set the size of the packet that is used to read and to write data to the FTP server
        'to the following specified size.
        Public Const BLOCK_SIZE = 512
        Private m_aBuffer(BLOCK_SIZE) As Byte
        Private ASCII As Encoding = Encoding.ASCII
        Public flag_bool As Boolean
        'General variable declaration
        Private m_sMessageString As String
#End Region

#Region "Class Constructors"
        ''' <summary>
        ''' Main class constructor
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New()
            m_sRemoteHost = ""
            m_sRemotePath = ""
            m_sRemoteUser = ""
            m_sRemotePassword = ""
            m_sMessageString = ""
            m_iRemotePort = 21
            m_bLoggedIn = False
            Me.m_sReceiveTimeout = 0
            Me.m_sSendTimeout = 0
        End Sub
        ''' <summary>
        ''' Parameterized constructor
        ''' </summary>
        ''' <param name="sRemoteHost">The remote host what will be use</param>
        ''' <param name="sRemotePath">Remote path</param>
        ''' <param name="sRemoteUser">Remote User</param>
        ''' <param name="sRemotePassword">Remote password</param>
        ''' <param name="iRemotePort">Remote Port</param>
        ''' <remarks></remarks>
        Public Sub New(ByVal sRemoteHost As String, _
                       ByVal sRemotePath As String, _
                       ByVal sRemoteUser As String, _
                       ByVal sRemotePassword As String, _
                       ByVal iRemotePort As Int32)
            m_sRemoteHost = sRemoteHost
            m_sRemotePath = sRemotePath
            m_sRemoteUser = sRemoteUser
            m_sRemotePassword = sRemotePassword
            m_sMessageString = ""
            m_iRemotePort = 21
            m_bLoggedIn = False
            Me.m_sReceiveTimeout = 0
            Me.m_sSendTimeout = 0
        End Sub
#End Region

#Region "Public Properties"
        ''' <summary>
        ''' Set or Get the name of the FTP server that you want to connect to.
        ''' </summary>
        ''' <value></value>
        ''' <returns>name of the FTP Server </returns>
        ''' <remarks></remarks>
        Public Property RemoteHostFTPServer() As String
            'Get the name of the FTP server.
            Get
                Return m_sRemoteHost
            End Get
            'Set the name of the FTP server.
            Set(ByVal Value As String)
                m_sRemoteHost = Value
            End Set
        End Property

        ''' <summary>
        ''' Set or Get the FTP port number of the FTP server that you want to connect to.
        ''' </summary>
        ''' <value></value>
        ''' <returns>number of the FTP server</returns>
        ''' <remarks></remarks>
        Public Property RemotePort() As Int32
            'Get the FTP port number.
            Get
                Return m_iRemotePort
            End Get
            'Set the FTP port number.
            Set(ByVal Value As Int32)
                m_iRemotePort = Value

            End Set
        End Property
        ''' <summary>
        ''' Set or Get the remote path of the FTP server that you want to connect to.
        ''' </summary>
        ''' <value></value>
        ''' <returns>path of the FTP server</returns>
        ''' <remarks></remarks>
        Public Property RemotePath() As String
            'Get the remote path.
            Get
                Return m_sRemotePath
            End Get
            'Set the remote path.
            Set(ByVal Value As String)
                m_sRemotePath = Value
            End Set
        End Property

        ''' <summary>
        ''' Set the remote password of the FTP server that you want to connect to.
        ''' </summary>
        ''' <value></value>
        ''' <returns>password</returns>
        ''' <remarks></remarks>
        Public Property RemotePassword() As String
            Get
                Return m_sRemotePassword
            End Get
            Set(ByVal Value As String)
                m_sRemotePassword = Value
            End Set
        End Property

        ''' <summary>
        ''' Set or Get the remote user of the FTP server that you want to connect to.
        ''' </summary>
        ''' <value></value>
        ''' <returns>name of the remote user</returns>
        ''' <remarks></remarks>
        Public Property RemoteUser() As String
            Get
                Return m_sRemoteUser
            End Get
            Set(ByVal Value As String)
                m_sRemoteUser = Value
            End Set
        End Property

        ''' <summary>
        ''' Set the class messagestring.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property MessageString() As String
            Get
                Return m_sMessageString
            End Get
            Set(ByVal Value As String)
                m_sMessageString = Value
            End Set
        End Property


        ''' <summary>
        ''' Sets or gets the timeout to send a package
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property SendTimeout() As Integer
            Get
                Return m_sSendTimeout
            End Get
            Set(ByVal value As Integer)
                m_sSendTimeout = value
                If Me.m_objClientSocket IsNot Nothing Then
                    Me.m_objClientSocket.SendTimeout = value
                End If
            End Set
        End Property


        ''' <summary>
        ''' Sets or gets the timeout to receive a package
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property ReceiveTimeout() As Integer
            Get
                Return m_sReceiveTimeout
            End Get
            Set(ByVal value As Integer)
                m_sReceiveTimeout = value
                If Me.m_objClientSocket IsNot Nothing Then
                    Me.m_objClientSocket.ReceiveTimeout = value
                End If
            End Set
        End Property

#End Region

#Region "Public Subs and Functions"


        ''' <summary>
        ''' Return a list of files from the file system. Return these files in a string() array.
        ''' </summary>
        ''' <param name="sMask"></param>
        ''' <returns>list of the files
        ''' </returns>
        ''' <remarks></remarks>
        Public Function GetFileList(ByVal sMask As String) As String()
            Dim cSocket As Socket
            Dim bytes As Int32
            Dim separator As Char = ControlChars.Lf
            Dim mess() As String

            m_sMes = ""
            'Check to see if you are logged on to the FTP server.
            If (Not (m_bLoggedIn)) Then
                Login()
            End If

            cSocket = CreateDataSocket()
            'Send an FTP command.
            SendCommand("NLST " & sMask)

            'If m_iRetValue <> 150 Then
            '    MessageString = m_sReply
            '    Throw New IOException(m_sReply.Substring(4))
            'End If


            m_sMes = ""
            Do While (True)
                Array.Clear(m_aBuffer, 0, m_aBuffer.Length)
                bytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
                m_sMes += ASCII.GetString(m_aBuffer, 0, bytes)

                If (bytes < m_aBuffer.Length) Then
                    Exit Do
                End If
            Loop

            mess = m_sMes.Split(separator)
            cSocket.Close()
            ReadReply()

            If (m_iRetValue <> 226) Then
                MessageString = m_sReply
                Throw New IOException(m_sReply.Substring(4))
            End If
            Return mess
        End Function

        ''' <summary>
        ''' Get the size of the file on the FTP server.
        ''' </summary>
        ''' <param name="sFileName">name of the file path</param>
        ''' <returns>number of the size of the file</returns>
        ''' <remarks></remarks>
        Public Function GetFileSize(ByVal sFileName As String) As Long
            Dim size As Long

            If (Not (m_bLoggedIn)) Then
                Login()
            End If
            'Send an FTP command.
            SendCommand("SIZE " & sFileName)
            size = 0

            If (m_iRetValue = 213) Then
                size = Int64.Parse(m_sReply.Substring(4))
            Else
                MessageString = m_sReply
                Throw New IOException(m_sReply.Substring(4))
            End If

            Return size
        End Function


        ''' <summary>
        ''' Log on to the FTP server.
        ''' </summary>
        ''' <returns>if the log on was successful send true, in other case send False</returns>
        ''' <remarks></remarks>
        Public Function Login() As Boolean

            m_objClientSocket = _
            New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            Me.m_objClientSocket.SendTimeout = Me.SendTimeout
            Me.m_objClientSocket.ReceiveTimeout = Me.ReceiveTimeout
            Dim ep As New IPEndPoint(Dns.GetHostEntry(m_sRemoteHost).AddressList(0), m_iRemotePort)
            Try
                m_objClientSocket.Connect(ep)
            Catch ex As Exception
                MessageString = m_sReply
                Throw New IOException("Cannot connect to the remote server")

            End Try

            ReadReply()
            If (m_iRetValue <> 220) Then
                CloseConnection()
                MessageString = m_sReply
                Throw New IOException(m_sReply.Substring(4))
            End If
            'Send an FTP command to send a user logon ID to the server.
            SendCommand("USER " & m_sRemoteUser)
            If (Not (m_iRetValue = 331 Or m_iRetValue = 230)) Then
                Cleanup()
                MessageString = m_sReply
                Throw New IOException(m_sReply.Substring(4))
            End If

            If (m_iRetValue <> 230) Then
                'Send an FTP command to send a user logon password to the server.
                SendCommand("PASS " & m_sRemotePassword)
                If (Not (m_iRetValue = 230 Or m_iRetValue = 202)) Then
                    Cleanup()
                    MessageString = m_sReply
                    Throw New IOException(m_sReply.Substring(4))
                End If
            End If

            m_bLoggedIn = True
            'Call the ChangeDirectory user-defined function to change the directory to the
            'remote FTP folder that is mapped.
            ChangeDirectory(m_sRemotePath)

            'Return the final result.
            Return m_bLoggedIn
        End Function

        ''' <summary>
        ''' If the value of mode is true, set binary mode for downloads. Otherwise, set ASCII mode.
        ''' </summary>
        ''' <param name="bMode">choose if you want binary or ASCII type</param>
        ''' <remarks></remarks>
        Public Sub SetBinaryMode(ByVal bMode As Boolean)

            If (bMode) Then
                'Send the FTP command to set the binary mode.
                '(TYPE is an FTP command that is used to specify representation type.)
                SendCommand("TYPE I")
            Else
                'Send the FTP command to set ASCII mode.
                '(TYPE is an FTP command that is used to specify representation type.)
                SendCommand("TYPE A")
            End If

            If (m_iRetValue <> 200) Then
                MessageString = m_sReply
                Throw New IOException(m_sReply.Substring(4))
            End If
        End Sub

        ''' <summary>
        ''' Download a file to the local directory of the assembly. Keep the same file name.
        ''' </summary>
        ''' <param name="sFileName">the name of the file</param>
        ''' <remarks></remarks>
        Public Sub DownloadFile(ByVal sFileName As String)
            DownloadFile(sFileName, "", False)
        End Sub

        ''' <summary>
        ''' Download a remote file to the local directory of the Assembly. Keep the same file name.
        ''' </summary>
        ''' <param name="sFileName">name of the file</param>
        ''' <param name="bResume"></param>
        ''' <remarks></remarks>
        Public Sub DownloadFile(ByVal sFileName As String, _
                                ByVal bResume As Boolean)
            DownloadFile(sFileName, "", bResume)
        End Sub
        ''' <summary>
        ''' Download a remote file to a local file name. You must include a path.
        ''' The local file name will be created or will be overwritten, but the path must exist.
        ''' </summary>
        ''' <param name="sFileName"></param>
        ''' <param name="sLocalFileName"></param>
        ''' <remarks></remarks>
        Public Sub DownloadFile(ByVal sFileName As String, ByVal sLocalFileName As String)
            DownloadFile(sFileName, sLocalFileName, False)
        End Sub

        ''' <summary>
        ''' Download a remote file to a local file name. You must include a path. Set the
        ''' resume flag. The local file name will be created or will be overwritten, but the path must exist.
        ''' </summary>
        ''' <param name="sFileName">name of the file where you are going to download</param>
        ''' <param name="sLocalFileName">name of the file where will put the new file</param>
        ''' <param name="bResume">in case of fail this try again download the file</param>
        ''' <remarks></remarks>
        Public Sub DownloadFile(ByVal sFileName As String, _
                                ByVal sLocalFileName As String, _
                                ByVal bResume As Boolean)
            Dim st As Stream
            Dim output As FileStream
            Dim cSocket As Socket
            Dim offset, npos As Long

            If (Not (m_bLoggedIn)) Then
                Login()
            End If

            SetBinaryMode(True)

            If (sLocalFileName.Equals("")) Then
                sLocalFileName = sFileName
            End If

            If (Not (File.Exists(sLocalFileName))) Then
                st = File.Create(sLocalFileName)
                st.Close()
            End If


            output = New FileStream(sLocalFileName, FileMode.Open)
            Try
                cSocket = CreateDataSocket()
                offset = 0
                If (bResume) Then
                    offset = output.Length

                    If (offset > 0) Then
                        'Send an FTP command to restart.
                        SendCommand("REST " & offset)
                        If (m_iRetValue <> 350) Then
                            offset = 0
                        End If
                    End If

                    If (offset > 0) Then
                        npos = output.Seek(offset, SeekOrigin.Begin)
                    End If
                End If
                'Send an FTP command to retrieve a file.
                SendCommand("RETR " & sFileName)

                If (Not (m_iRetValue = 150 Or m_iRetValue = 125)) Then
                    MessageString = m_sReply
                    Throw New IOException(m_sReply.Substring(4))
                End If

                Do While (True)
                    Array.Clear(m_aBuffer, 0, m_aBuffer.Length)
                    m_iBytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
                    output.Write(m_aBuffer, 0, m_iBytes)

                    If (m_iBytes <= 0) Then
                        Exit Do
                    End If
                Loop

            Catch ex As Exception
                Throw ex
            Finally
                output.Close()
                If cSocket IsNot Nothing AndAlso (cSocket.Connected) Then
                    cSocket.Close()
                End If
            End Try
            ReadReply()
            If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then
                MessageString = m_sReply
                Throw New IOException(m_sReply.Substring(4))
            End If
        End Sub

        ''' <summary>
        ''' This is a function that is used to upload a file from your local hard disk to your FTP site.
        ''' </summary>
        ''' <param name="sFileName">name of the file what going to be upload from inFTP site</param>
        ''' <remarks></remarks>
        Public Sub UploadFile(ByVal sFileName As String)
            UploadFile(sFileName, False)
        End Sub

        ''' <summary>
        ''' This is a function that is used to upload a file from your local hard disk to your FTP site
        ''' and then set the resume flag.
        ''' </summary>
        ''' <param name="sFileName">name oif the file</param>
        ''' <param name="bResume">in case of fail this try again download the file</param>
        ''' <remarks></remarks>
        Public Sub UploadFile(ByVal sFileName As String, _
                              ByVal bResume As Boolean)
            Dim cSocket As Socket
            Dim offset As Long
            Dim input As FileStream
            Dim bFileNotFound As Boolean

            If (Not (m_bLoggedIn)) Then
                Login()
            End If

            cSocket = CreateDataSocket()
            offset = 0

            If (bResume) Then
                Try
                    SetBinaryMode(True)
                    offset = GetFileSize(sFileName)
                Catch ex As Exception
                    offset = 0
                End Try
            End If

            If (offset > 0) Then
                SendCommand("REST " & offset)
                If (m_iRetValue <> 350) Then

                    'The remote server may not support resuming.
                    offset = 0
                End If
            End If
            'Send an FTP command to store a file.
            SendCommand("STOR " & Path.GetFileName(sFileName))
            If (Not (m_iRetValue = 125 Or m_iRetValue = 150)) Then
                MessageString = m_sReply
                Throw New IOException(m_sReply.Substring(4))
            End If

            'Check to see if the file exists before the upload.
            bFileNotFound = False
            If (File.Exists(sFileName)) Then
                ' Open the input stream to read the source file.
                input = New FileStream(sFileName, FileMode.Open)
                If (offset <> 0) Then
                    input.Seek(offset, SeekOrigin.Begin)
                End If

                'Upload the file.
                m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length)
                Do While (m_iBytes > 0)
                    cSocket.Send(m_aBuffer, m_iBytes, 0)
                    m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length)
                Loop
                input.Close()
            Else
                bFileNotFound = True
            End If

            If (cSocket.Connected) Then
                cSocket.Close()
            End If

            'Check the return value if the file was not found.
            If (bFileNotFound) Then
                MessageString = m_sReply
                Throw New IOException("The file: " & sFileName & " was not found. " & _
               "Cannot upload the file to the FTP site")
            End If

            ReadReply()
            If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then
                MessageString = m_sReply
                Throw New IOException(m_sReply.Substring(4))
            End If
        End Sub
        ''' <summary>
        ''' Delete a file from the remote FTP server.
        ''' </summary>
        ''' <param name="sFileName">name of the file</param>
        ''' <returns>if the file was successfully deleted send true, in other case false</returns>
        ''' <remarks></remarks>
        Public Function DeleteFile(ByVal sFileName As String) As Boolean
            Dim bResult As Boolean

            bResult = True
            If (Not (m_bLoggedIn)) Then
                Login()
            End If
            'Send an FTP command to delete a file.
            SendCommand("DELE " & sFileName)
            If (m_iRetValue <> 250) Then
                bResult = False
                MessageString = m_sReply
            End If

            ' Return the final result.
            Return bResult
        End Function
        ''' <summary>
        ''' Rename a file on the remote FTP server.
        ''' </summary>
        ''' <param name="sOldFileName">old name of the file</param>
        ''' <param name="sNewFileName">new name of the file</param>
        ''' <returns>if the file was successfully rename send true, in other case false</returns>
        ''' <remarks></remarks>
        Public Function RenameFile(ByVal sOldFileName As String, _
                                   ByVal sNewFileName As String) As Boolean
            Dim bResult As Boolean

            bResult = True
            If (Not (m_bLoggedIn)) Then
                Login()
            End If
            'Send an FTP command to rename from a file.
            SendCommand("RNFR " & sOldFileName)
            If (m_iRetValue <> 350) Then
                MessageString = m_sReply
                Throw New IOException(m_sReply.Substring(4))
            End If

            'Send an FTP command to rename a file to a new file name.
            'It will overwrite if newFileName exists.
            SendCommand("RNTO " & sNewFileName)
            If (m_iRetValue <> 250) Then
                MessageString = m_sReply
                Throw New IOException(m_sReply.Substring(4))
            End If
            ' Return the final result.
            Return bResult
        End Function

        ''' <summary>
        ''' This is a function that is used to create a directory on the remote FTP server.
        ''' </summary>
        ''' <param name="sDirName">name of the new directory</param>
        ''' <returns>if the directory was successfully made send true, in other case false</returns>
        ''' <remarks></remarks>
        Public Function CreateDirectory(ByVal sDirName As String) As Boolean
            Dim bResult As Boolean

            bResult = True
            If (Not (m_bLoggedIn)) Then
                Login()
            End If
            'Send an FTP command to make directory on the FTP server.
            SendCommand("MKD " & sDirName)
            If (m_iRetValue <> 257) Then
                bResult = False
                MessageString = m_sReply
            End If

            ' Return the final result.
            Return bResult
        End Function
        ''' <summary>
        ''' This is a function that is used to delete a directory on the remote FTP server.
        ''' </summary>
        ''' <param name="sDirName">name the directory that going to be deleted</param>
        ''' <returns>if the directory was successfully deleted send true, in other case false</returns>
        ''' <remarks></remarks>
        Public Function RemoveDirectory(ByVal sDirName As String) As Boolean
            Dim bResult As Boolean

            bResult = True
            'Check if logged on to the FTP server
            If (Not (m_bLoggedIn)) Then
                Login()
            End If
            'Send an FTP command to remove directory on the FTP server.
            SendCommand("RMD " & sDirName)
            If (m_iRetValue <> 250) Then
                bResult = False
                MessageString = m_sReply
            End If

            ' Return the final result.
            Return bResult
        End Function
        ''' <summary>
        ''' This is a function that is used to change the current working directory on the remote FTP server.
        ''' </summary>
        ''' <param name="sDirName">name of the directory who are going to change</param>
        ''' <returns>if the directory was successfully changed send true, in other case false</returns>
        ''' <remarks></remarks>
        Public Function ChangeDirectory(ByVal sDirName As String) As Boolean
            Dim bResult As Boolean

            bResult = True
            'Check if you are in the root directory.
            If (sDirName.Equals(".")) Then
                Exit Function
            End If
            'Check if logged on to the FTP server
            If (Not (m_bLoggedIn)) Then
                Login()
            End If
            'Send an FTP command to change directory on the FTP server.
            SendCommand("CWD " & sDirName)
            If (m_iRetValue <> 250) Then
                bResult = False
                MessageString = m_sReply
            End If

            Me.m_sRemotePath = sDirName

            ' Return the final result.
            Return bResult
        End Function
        ''' <summary>
        ''' Close the FTP connection of the remote server.
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub CloseConnection()
            If (Not (m_objClientSocket Is Nothing)) Then
                'Send an FTP command to end an FTP server system.
                SendCommand("QUIT")
            End If

            Cleanup()
        End Sub

#End Region

#Region "Private Subs and Functions"
        ''' <summary>
        ''' Read the reply from the FTP server.
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub ReadReply()
            m_sMes = ""
            m_sReply = ReadLine()
            m_iRetValue = Int32.Parse(m_sReply.Substring(0, 3))
        End Sub

        ''' <summary>
        ''' Clean up some variables.
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub Cleanup()
            If Not (m_objClientSocket Is Nothing) Then
                m_objClientSocket.Close()
                m_objClientSocket = Nothing
            End If

            m_bLoggedIn = False
        End Sub
        ''' <summary>
        ''' Read a line from the FTP server.
        ''' </summary>
        ''' <param name="bClearMes"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function ReadLine(Optional ByVal bClearMes As Boolean = False) As String
            Dim seperator As Char = ControlChars.Lf
            Dim mess() As String

            If (bClearMes) Then
                m_sMes = ""
            End If
            Do While (True)
                Array.Clear(m_aBuffer, 0, BLOCK_SIZE)
                m_iBytes = m_objClientSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
                m_sMes += ASCII.GetString(m_aBuffer, 0, m_iBytes)
                If (m_iBytes < m_aBuffer.Length) Then
                    Exit Do
                End If
            Loop

            mess = m_sMes.Split(seperator)
            If (m_sMes.Length > 2) Then
                m_sMes = mess(mess.Length - 2)
            Else
                m_sMes = mess(0)
            End If

            If (Not (m_sMes.Substring(3, 1).Equals(" "))) Then
                Return ReadLine(True)
            End If

            Return m_sMes
        End Function
        ''' <summary>
        ''' This is a function that is used to send a command to the FTP server that you are connected to.
        ''' </summary>
        ''' <param name="sCommand"></param>
        ''' <remarks></remarks>
        Private Sub SendCommand(ByVal sCommand As String)
            sCommand = sCommand & ControlChars.CrLf
            Dim cmdbytes As Byte() = ASCII.GetBytes(sCommand)
            m_objClientSocket.Send(cmdbytes, cmdbytes.Length, 0)
            ReadReply()
        End Sub
        ''' <summary>
        '''  Create a data socket.
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function CreateDataSocket() As Socket
            Dim index1, index2, len As Int32
            Dim partCount, i, port As Int32
            Dim ipData, buf, ipAddress As String
            Dim parts(6) As Int32
            Dim ch As Char
            Dim s As Socket
            Dim ep As IPEndPoint
            'Send an FTP command to use passive data connection.
            SendCommand("PASV")
            If (m_iRetValue <> 227) Then
                MessageString = m_sReply
                Throw New IOException(m_sReply.Substring(4))
            End If

            index1 = m_sReply.IndexOf("(")
            index2 = m_sReply.IndexOf(")")
            ipData = m_sReply.Substring(index1 + 1, index2 - index1 - 1)

            len = ipData.Length
            partCount = 0
            buf = ""

            For i = 0 To ((len - 1) And partCount <= 6)
                ch = Char.Parse(ipData.Substring(i, 1))
                If (Char.IsDigit(ch)) Then
                    buf += ch
                ElseIf (ch <> ",") Then
                    MessageString = m_sReply
                    Throw New IOException("Malformed PASV reply: " & m_sReply)
                End If

                If ((ch = ",") Or (i + 1 = len)) Then
                    Try
                        parts(partCount) = Int32.Parse(buf)
                        partCount += 1
                        buf = ""
                    Catch ex As Exception
                        MessageString = m_sReply
                        Throw New IOException("Malformed PASV reply: " & m_sReply)
                    End Try
                End If
            Next

            ipAddress = parts(0) & "." & parts(1) & "." & parts(2) & "." & parts(3)

            ' Make this call in Visual Basic .NET 2002. You want to
            ' bitshift the number by 8 bits. In Visual Basic .NET 2002 you must
            ' multiply the number by 2 to the power of 8.
            'port = parts(4) * (2 ^ 8)

            ' Make this call and then comment out the previous line for Visual Basic .NET 2003.
            port = parts(4) << 8

            ' Determine the data port number.
            port = port + parts(5)

            s = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            s.SendTimeout = Me.SendTimeout
            s.ReceiveTimeout = Me.ReceiveTimeout
            ep = New IPEndPoint(Dns.GetHostEntry(ipAddress).AddressList(0), port)

            Try
                s.Connect(ep)
            Catch ex As Exception
                MessageString = m_sReply
                Throw New IOException("Cannot connect to remote server.")
                'If you cannot connect to the FTP server that is
                'specified, make the boolean variable false.
                flag_bool = False
            End Try
            'If you can connect to the FTP server that is specified, make the boolean variable true.
            flag_bool = True
            Return s
        End Function

#End Region


        Public Sub Dispose()
            If Me.m_objClientSocket IsNot Nothing AndAlso Me.m_objClientSocket.Connected Then
                Me.m_objClientSocket.Shutdown(SocketShutdown.Both)
                Me.m_objClientSocket.Disconnect(False)
            End If
        End Sub
    End Class
End Namespace